package com.itheima.server.service;

import com.github.tobato.fastdfs.domain.conn.FdfsWebServer;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.itheima.commons.template.OssTemplate;
import com.itheima.domain.db.UserInfo;
import com.itheima.domain.mongo.Comment;
import com.itheima.domain.mongo.Video;
import com.itheima.domain.vo.CommentVo;
import com.itheima.domain.vo.PageResult;
import com.itheima.domain.vo.VideoVo;
import com.itheima.dubbo.api.CommentApi;
import com.itheima.dubbo.api.FollowUserApi;
import com.itheima.dubbo.api.UserInfoApi;
import com.itheima.dubbo.api.VideoApi;
import com.itheima.server.interceptor.UserHolder;
import com.itheima.server.util.RelativeDateFormat;
import org.apache.dubbo.config.annotation.Reference;
import org.bson.types.ObjectId;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author 阿鹏
 * @date 2021/1/30 21:15
 */
@Service
public class SmallVideoService {

    @Reference
    private VideoApi videoApi;
    @Reference
    private UserInfoApi userInfoApi;
    @Reference
    private FollowUserApi followUserApi;
    @Reference
    private CommentApi commentApi;
    @Autowired
    private OssTemplate ossTemplate;
    @Autowired
    private FastFileStorageClient client;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    private FdfsWebServer fdfsWebServer;
    @Autowired
    private VideoMQService videoMQService;

    //@CacheEvict(cacheNames = "videoList",allEntries = true)
    public ResponseEntity saveSmallVideos(MultipartFile videoThumbnail, MultipartFile videoFile) throws IOException {
        // 1.将封面图片上传到阿里云
        String picUrl = ossTemplate.upload(videoThumbnail.getOriginalFilename(), videoThumbnail.getInputStream());
        // 截取后缀,上传到fastdfs文件系统
        String suffix = videoFile.getOriginalFilename().substring(videoFile.getOriginalFilename().lastIndexOf(".") + 1);
        StorePath storePath = client.uploadFile(videoFile.getInputStream(), videoFile.getSize(), suffix, null);
        // WebServerUrl为yml文件中配置的信息,可以通过fdfsWebServer获取
        String videoUrl = fdfsWebServer.getWebServerUrl() + storePath.getFullPath();

        // 封装video信息数据
        Video video = new Video();
        video.setPicUrl(picUrl);
        video.setVideoUrl(videoUrl);
        video.setUserId(UserHolder.getUserId());
        video.setText("年轻人的第一个短视频");

        // 调用api,保存视频信息
        String videoId = videoApi.save(video);

        videoMQService.saveVideoMessage(videoId);
        return ResponseEntity.ok(null);
    }

    //@Cacheable(cacheNames = "videoList",key = "#page + '_' + #pagesize")
    public PageResult<VideoVo> getSmallVideosList(Integer page, Integer pagesize) {

        PageResult<Video> pageResult = findVideoFromRedis(page, pagesize);
        if (pageResult == null) {
            pageResult = videoApi.findVideoList(page, pagesize);
        }

        List<VideoVo> voList = new ArrayList<>();
        for (Video video : pageResult.getItems()) {
            VideoVo vo = new VideoVo();
            BeanUtils.copyProperties(video, vo);

            vo.setId(video.getId().toHexString());
            vo.setHasFocus(0);
            vo.setCover(video.getPicUrl());
            vo.setSignature(video.getText());

            UserInfo userInfo = userInfoApi.findById(video.getUserId());
            BeanUtils.copyProperties(userInfo, vo);
            Boolean hasLike = redisTemplate.hasKey("video_user_like_" + UserHolder.getUserId() + "_" + video.getId().toHexString());
            vo.setHasLiked(hasLike ? 1 : 0);
            Boolean hasFocus = redisTemplate.hasKey("follow_user_" + UserHolder.getUserId() + "_" + video.getUserId());
            vo.setHasFocus(hasFocus ? 1 : 0);

            voList.add(vo);
        }

        PageResult<VideoVo> voPageResult = new PageResult<>();
        BeanUtils.copyProperties(pageResult, voPageResult);
        voPageResult.setItems(voList);
        return voPageResult;
    }

    private PageResult<Video> findVideoFromRedis(Integer page, Integer pagesize) {
        String vidStr = redisTemplate.opsForValue().get("QUANZI_VIDEO_RECOMMEND_" + UserHolder.getUserId());
        if (vidStr == null) {
            return null;
        }
        String[] vidArray = vidStr.split(",");
        int count = vidArray.length;
        int pages = (int) Math.ceil(count * 1.0 / pagesize);

        if (page <= pages) {
            int start = (page - 1) * pagesize;
            int end = start + pagesize;
            if (end > count) {
                end = count;
            }

            List<Long> vidList = new ArrayList<>();
            for (int i = start; i < end; i++) {
                Long vid = Long.valueOf(vidArray[i]);
                vidList.add(vid);
            }
            List<Video> videoList = videoApi.findVideoListByVidList(vidList);

            return new PageResult<>(count, pagesize, pages, page, videoList);
        }

        return new PageResult<>();
    }

    public ResponseEntity saveUserFocus(long followUserId) {

        followUserApi.followUser(UserHolder.getUserId(), followUserId);
        redisTemplate.opsForValue().set("follow_user_" + UserHolder.getUserId() + "_" + followUserId, "1");
        return ResponseEntity.ok(null);
    }

    public ResponseEntity removeUserFocus(long followUserId) {
        Long userId = UserHolder.getUserId();
        followUserApi.disFollowUser(userId, followUserId);
        redisTemplate.delete("follow_user_" + userId + "_" + followUserId);
        return ResponseEntity.ok(null);
    }


    public ResponseEntity saveLike(String videoId) {
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(videoId));
        comment.setCommentType(1);
        comment.setPubType(2);
        comment.setUserId(UserHolder.getUserId());
        Video video = videoApi.findVideoById(videoId);
        comment.setPublishUserId(video.getUserId());

        long count = commentApi.saveOtherComment(comment);

        redisTemplate.opsForValue().set("video_user_like_" + UserHolder.getUserId() + "_" + videoId, "1");
        return ResponseEntity.ok(count);
    }

    public ResponseEntity removeLike(String videoId) {
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(videoId));
        comment.setPubType(2);
        comment.setCommentType(1);
        comment.setUserId(UserHolder.getUserId());
        long count = commentApi.removeOtherComment(comment);

        redisTemplate.delete("video_user_like_" + UserHolder.getUserId() + "_" + videoId);
        return ResponseEntity.ok(count);
    }

    public ResponseEntity saveComments(String videoId, String content) {
        Comment comment = new Comment();
        comment.setUserId(UserHolder.getUserId());
        comment.setPubType(2);
        comment.setCommentType(2);
        comment.setContent(content);
        comment.setPublishId(new ObjectId(videoId));
        Video video = videoApi.findVideoById(videoId);
        comment.setPublishUserId(video.getUserId());

        commentApi.saveOtherComment(comment);

        return ResponseEntity.ok(null);
    }

    public ResponseEntity queryCommentList(String videoId, int page, int pagesize) {
        PageResult<Comment> pageResult = commentApi.findComments(page, pagesize, videoId);
        List<CommentVo> volist = new ArrayList<>();
        for (Comment comment : pageResult.getItems()) {
            CommentVo vo = new CommentVo();
            UserInfo userInfo = userInfoApi.findById(comment.getUserId());
            BeanUtils.copyProperties(userInfo, vo);
            BeanUtils.copyProperties(comment, vo);
            vo.setId(comment.getId().toHexString());
            vo.setCreateDate(RelativeDateFormat.format(new Date(comment.getCreated())));

            Boolean hasLike =
                    redisTemplate.hasKey("video_comment_user_" + UserHolder.getUserId() + "_" + comment.getId().toHexString());
            vo.setHasLiked(hasLike ? 1 : 0);

            volist.add(vo);
        }

        PageResult<CommentVo> voPageResult = new PageResult<>();
        BeanUtils.copyProperties(pageResult, voPageResult);
        voPageResult.setItems(volist);
        return ResponseEntity.ok(voPageResult);
    }

    public ResponseEntity saveCommentLike(String commentId) {
        Comment comment = new Comment();
        comment.setCommentType(1);
        comment.setPubType(3);
        comment.setUserId(UserHolder.getUserId());
        comment.setPublishId(new ObjectId(commentId));
        Comment comment1 = commentApi.findCommentByCommentId(commentId);
        comment.setPublishUserId(comment1.getPublishUserId());

        long count = commentApi.saveOtherComment(comment);

        redisTemplate.opsForValue().set("video_comment_user_" + UserHolder.getUserId() + "_" + commentId, "1");
        return ResponseEntity.ok(count);
    }

    public ResponseEntity removeCommentLike(String commentId) {
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(commentId));
        comment.setPubType(3);
        comment.setCommentType(1);
        comment.setUserId(UserHolder.getUserId());

        long count = commentApi.removeOtherComment(comment);

        redisTemplate.delete("video_comment_user_" + UserHolder.getUserId() + "_" + commentId);
        return ResponseEntity.ok(count);
    }
}
